﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace DTO
{
    public class FilterParameter
    {
        public string direct { get; set; }
        public string name { get; set; }
        public string prefixVal { get; set; }
        string _method = "=";

        public string method
        {
            get { return _method; }
            set { _method = value; }
        }
        public object value { get; set; }

        public string ToFilterString()
        {
            string res = "";
            if (value is object[])
            {
                if (method.ToLower() == "between")
                {
                    object[] tmp = value as object[];
                    if (tmp.Length < 2)
                    {
                        method = "=";
                        res = string.Format("({0} {1} @{2}{3})", getField(), method, prefixVal, name);
                    }
                    else
                    {
                        string val = "";
                        for (int j = 0; j < 2; j++)
                        {
                            if (j != 0) val += " AND ";
                            val += string.Format("@{0}{1}{2}", prefixVal, name, j);
                        }

                        res = string.Format("({0} {1} {2})", getField(), method, val);
                    }
                }
                else
                {
                    object[] tmp = value as object[];
                    string val = "";
                    for (int j = 0; j < tmp.Length; j++)
                    {
                        if (j != 0) val += ",";
                        val += string.Format("@{0}{1}{2}", prefixVal, name, j);
                    }

                    res = string.Format("{0} {1} ({2})", getField(), method, val);
                }
            }
            else
            {
                res = string.Format("{0} {1} @{2}{3}", getField(), method, prefixVal, name);
            }
            return res;

        }

        private string getField()
        {
            if (string.IsNullOrEmpty(direct)) return name;
            return string.Format("{0}.{1}", direct, name);
        }

        public string ReplaceResult(string fs)
        {
            if (value is object[])
            {
                object[] tmp = value as object[];
                int len = tmp.Length;
                if (method.ToLower() == "between") len = 2;
                for (int j = 0; j < len; j++)
                {
                    fs = fs.Replace(string.Format("@{0}{1}", name, j), FormatValue(tmp[j]));
                }
            }
            else
            {
                fs = fs.Replace(string.Format("@{0}", name), FormatValue(value));
            }

            return fs;
        }

        private string FormatValue(object p)
        {
            if (p is double || p is int) return p.ToString();
            if (p is DateTime) return string.Format("'{0:yyyy-MM-dd}'", p);
            if (p == null) return "NULL";
            if (method.ToLower() == "like") return string.Format("'%{0}%'", p.ToString().Replace(@"'", "''"));
            return string.Format("'{0}'", p.ToString().Replace(@"'", "''"));
        }
    }

    public class FilterParameterCollection : List<FilterParameter>
    {
        public FilterParameter Find(string name)
        {
            if (name == string.Empty)
                return null;

            /*foreach (var c in this)
            {
                if (c.ObjectName.Equals(name))
                    return c;
            }
            return null;*/

            return this.FirstOrDefault(c => c.name.Equals(name));
        }

        public List<string> GetAllObjectNames()
        {
            /*var lst = new List<string>();
            foreach (var obj in this)
                lst.Add(obj.ObjectName);
            return lst;*/

            return this.Select(obj => obj.name).ToList();
        }
        public List<FilterParameter> ToList()
        {
            return this.ToList<FilterParameter>();
        }
        public string FindNameAvailable(string item, int counter)
        {
            if (Find(item + (counter == 0 ? "" : "#" + counter)) == null)
                return item + (counter == 0 ? "" : "#" + counter);

            return FindNameAvailable(item, counter + 1);
        }

        public void InsertAtTop(FilterParameter item)
        {
            InsertAtTop(item, false);
        }

        public void InsertAtTop(string name, object value)
        {
            FilterParameter item = new FilterParameter() { name = name, value = value };
            InsertAtTop(item, false);
        }

        public void Add(string name, object value)
        {
            FilterParameter item = new FilterParameter() { name = name, value = value };
            Add(item);
        }

        public void InsertAtTop(FilterParameter item, bool isUnique)
        {
            if (isUnique)
                item.name = FindNameAvailable(item.name, 0);

            Insert(0, item);
        }

    }
}
